﻿$import( "SmitearWebGL.IO.ImageLoader" );
$import( "SmitearWebGL.Core.ResourceItem" );
$import( "SmitearWebGL.Core.Algorithm.PerlinNoise" );

SmitearWebGL.Resources.Bitmap = SmitearWebGL.Core.ResourceItem.extend(
{
	/******** constructor ********/

	init : function()
	{
		this._super();
		this._registClass( "SmitearWebGL.Resources.Bitmap" );
		
		/******** public property ********/

		/******** private property ********/

		this._canvas = null;
		this._flip = true;
		this._width = 0;
		this._height = 0;
	}
	,

	/******** public method ********/
	
	getWidth : function()
	{
		return this._width;
	}
	,
	getHeight : function()
	{
		return this._height;
	}
	,
	getCanvas : function()
	{
		return this._canvas;
	}
	,
	getFlip : function()
	{
		return this._flip;
	}
	,
	createBitmap : function( width, height, flip, pixels )
	{
		$THROW( this.isResourceCreated(), "该资源还没有被创建." );
		
		this._canvas = document.createElement("canvas");
		this._canvas.width = this._width = width;
		this._canvas.height = this._height = height;
		
		if ( pixels )
		{
			var context = this._canvas.getContext( "2d" );
			var imgd = context.createImageData( this._width, this._height );
			var pix = imgd.data;
			
			for ( var i = 0; n = pix.length, i < n; ++ i )
			{
				pix[i] = pixels[i];
			}
			
			context.putImageData( imgd, 0, 0 );
		}
		
		this._flip = flip;
	}
	,
	rotate : function( value )
	{
		$THROW( this.isResourceCreated(), "该资源还没有被创建." );
		$THROW( this._canvas != null, "Canvas实例还没有被创建." );
		
		var temp_canvas = document.createElement("canvas");
		
		var context = temp_canvas.getContext( "2d" );
		
		switch ( value )
		{
			case 0:
				temp_canvas.width = this._canvas.width;
				temp_canvas.height = this._canvas.height;
				context.rotate( value * Math.PI / 180.0 );
				context.drawImage( this._canvas, 0, 0 );
				break;
				
			case 90:
				temp_canvas.width = this._canvas.height;
				temp_canvas.height = this._canvas.width;
				context.rotate( value * Math.PI / 180.0 );
				context.drawImage( this._canvas, 0, -this._canvas.height );
				break;
				
			case 180:
				temp_canvas.width = this._canvas.width;
				temp_canvas.height = this._canvas.height;
				context.rotate( value * Math.PI / 180.0 );
				context.drawImage( this._canvas, -this._canvas.width, -this._canvas.height );
				break;
				
			case 270:
			case -90:
				temp_canvas.width = this._canvas.height;
				temp_canvas.height = this._canvas.width;
				context.rotate( value * Math.PI / 180.0 );
				context.drawImage( this._canvas, -this._canvas.width, 0 );
				break;
			
			default:
				$WARNING( "图像旋转只支持0, 90, 180, 270(-90)度的转换" );
				context.drawImage( this._canvas, 0, 0 );
				break;
		}
		
		this._canvas = temp_canvas;
	}
	,
	generatePerlinNoise : function( octaves, gain, type )
	{
		$THROW( this.isResourceCreated(), "该资源还没有被创建." );
		$THROW( this._canvas != null, "Canvas实例还没有被创建." );
	
		var color;
		var context = this._canvas.getContext( "2d" );
		var imgd = context.createImageData( this._width, this._height );
		var pix = imgd.data;
	
		if ( pix )
		{
			SmitearWebGL.Core.Algorithm.PerlinNoise.generate( pix, this._width, this._height, octaves, gain, type );
			context.putImageData( imgd, 0, 0 );
		}
	}
	,
	generateHeightTable : function( heightTable, scale, offset, channel )
	{
		$THROW( this.isResourceCreated(), "该资源还没有被创建." );
		$THROW( this._canvas != null, "Canvas实例还没有被创建." );
		
		if ( ! heightTable ) return;
		
		scale = scale || 1;
		offset = offset || 0;
		channel = channel || SmitearWebGL.Core.Math.Color.Channel.RED;
		
		var context = this._canvas.getContext( "2d" );
		var imgd = context.getImageData( 0, 0, this._width, this._height );
		var pix = imgd.data;
		var i = 0;
	
		if ( pix )
		{
			for( var y = 0; y < this._height; ++ y )
			{
				for( var x = 0; x < this._width; ++ x )
				{
					var iHeight = pix[i * 4 + channel];
					var fHeight = ( iHeight * scale ) + offset;
	
					heightTable[i] = fHeight;
	
					++ i;
				}
			}
		}
	}
	,
	generateNormalTable : function( normalTable, scale, channel )
	{
		$THROW( this.isResourceCreated(), "该资源还没有被创建." );
		$THROW( this._canvas != null, "Canvas实例还没有被创建." );
		
		if ( ! normalTable ) return;
		
		scale = scale || 1;
		channel = channel || SmitearWebGL.Core.Math.Color.Channel.RED;
	
		var mag = 0, i = 0;
		var north = 0,south = 0,west = 0,east = 0;
		var colorN = 0, colorS = 0, colorE = 0, colorW = 0;
		var v0, v1, v2;
	
		var context = this._canvas.getContext( "2d" );
		var imgd = context.getImageData( 0, 0, this._width, this._height );
		var pix = imgd.data;
	
		if ( pix )
		{
			for ( var y = 1; y < this._height - 1; ++ y )
			{
				for ( var x = 1; x < this._width - 1; ++ x )
				{
					colorN = pix[( ( y - 1 ) * this._width + x + 0 ) * 4 + channel];
					colorS = pix[( ( y + 1 ) * this._width + x + 0 ) * 4 + channel];
					colorE = pix[( ( y + 0 ) * this._width + x + 1 ) * 4 + channel];
					colorW = pix[( ( y + 0 ) * this._width + x - 1 ) * 4 + channel];
					
					i = 3 * ( x + y * this._width );
					
					v0 = colorW - colorE;
					v2 = colorS - colorN;
					v1 = scale * 2.0;
	
					mag = 1.0 / Math.sqrt( v0 * v0 + v1 * v1 + v2 * v2 );
					
					v0 *= mag;
					v1 *= mag;
					v2 *= mag;
					
					normalTable[i+0] = v0;
					normalTable[i+1] = v1;
					normalTable[i+2] = v2;
				}
			}
		}
	}
	,
	load : function( fileName )
	{
		var loader = new SmitearWebGL.IO.ImageLoader();
		loader.contentLoaderInfo.addEventListener( SmitearWebGL.Events.FileLoadEvent.FILE_LOAD_COMPLETE, this, this._loadCompleteHandler);
		loader.load( fileName );
	}
	,

	/******** inherit method ********/
	
	_destroyResource : function()
	{
		this._super();
		
		this._canvas = null;
		this._flip = true;
		this._width = 0;
		this._height = 0;
	}
	,
	_loadCompleteHandler : function( e )
	{
		var contentLoaderInfo = e.sender;
		contentLoaderInfo.removeEventListener( SmitearWebGL.Events.FileLoadEvent.FILE_LOAD_COMPLETE, this._loadCompleteHandler);

		this._canvas = this._drawToCanvas( contentLoaderInfo.content, false );
		this.dispatchEvent( new SmitearWebGL.Events.Event( SmitearWebGL.Resources.Bitmap.LOAD_COMPLETE ) );
	}
	,
	_drawToCanvas : function( htmlImageElement, flip )
	{
		$THROW( this.isResourceCreated(), "该资源还没有被创建." );
		
		if ( this._width == 0 ) this._width = htmlImageElement.width;
		if ( this._height == 0 ) this._height = htmlImageElement.height;

		var temp_canvas = document.createElement("canvas");
		temp_canvas.width = this._width;
		temp_canvas.height = this._height;
		
		var context = temp_canvas.getContext( "2d" );
		if ( flip )
		{
			context.translate( 0, this._height );
			context.scale( 1, - 1 );
		}
		context.drawImage( htmlImageElement, 0, 0, this._width, this._height );
		
		return temp_canvas;
	}
}
);

/******** static property ********/

SmitearWebGL.Resources.Bitmap.FACE_POSITIVE_X = 0;
SmitearWebGL.Resources.Bitmap.FACE_NEGATIVE_X = 1;
SmitearWebGL.Resources.Bitmap.FACE_POSITIVE_Y = 2;
SmitearWebGL.Resources.Bitmap.FACE_NEGATIVE_Y = 3;
SmitearWebGL.Resources.Bitmap.FACE_POSITIVE_Z = 4;
SmitearWebGL.Resources.Bitmap.FACE_NEGATIVE_Z = 5;
SmitearWebGL.Resources.Bitmap.IMAGE = 6;
SmitearWebGL.Resources.Bitmap.SLICE = 7;

SmitearWebGL.Resources.Bitmap.UNKNOWN_SEMANTIC = 0;

SmitearWebGL.Resources.Bitmap.scratch_canvas = null;

SmitearWebGL.Resources.Bitmap.LOAD_COMPLETE = "bitmap_load_complete";

/******** static method ********/

SmitearWebGL.Resources.Bitmap.createScratchCanvas = function( width, height )
{
	if (!SmitearWebGL.Resources.Bitmap.scratch_canvas)
		SmitearWebGL.Resources.Bitmap.scratch_canvas = document.createElement("canvas");
	
	SmitearWebGL.Resources.Bitmap.scratch_canvas.width = width;
	SmitearWebGL.Resources.Bitmap.scratch_canvas.height = height;	
		
	return SmitearWebGL.Resources.Bitmap.scratch_canvas;
}